package com.lzx.article.jobHandler;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lzx.article.entity.Articles;
import com.lzx.article.entity.Browse;
import com.lzx.article.entity.UserRecommend;
import com.lzx.article.feign.UserClient;
import com.lzx.article.mapper.ArticlesMapper;
import com.lzx.article.mapper.BrowseMapper;
import com.lzx.article.mapper.TwoSortMapper;
import com.lzx.article.mapper.UserRecommendMapper;
import com.lzx.article.utils.TypeConversion;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 程序员星星
 * @date 2023/2/4
 * @Description
 */
@Component
public class ArticleXxlJob {
    @Resource
    private BrowseMapper browseMapper;

    @Resource
    private UserClient userClient;

    @Resource
    private ArticlesMapper articlesMapper;

    @Resource
    private TwoSortMapper twoSortMapper;

    @Resource
    private UserRecommendMapper userRecommendMapper;

    //用户文章推荐
    @XxlJob("articleRecommendJobHandler")
    public void articleRecommendJobHandler() {
        //存放标签(key为标签id，value为权重)
        Map<String, Integer> mapLabel = new HashMap<>();
        //获取用户id列表
        List<Long> userIdList = userClient.getUserIdList();
        userIdList.forEach(userId -> {
            QueryWrapper<Browse> browseQueryWrapper = new QueryWrapper<>();
            browseQueryWrapper.eq("user_id", userId);
            //获取用户浏览记录
            List<Browse> browses = browseMapper.selectList(browseQueryWrapper);
            if (browses.size() != 0) {
                browses.forEach(browse -> {
                    Articles articles = articlesMapper.selectById(browse.getArticleId());
                    //标签id数组
                    List<String> ids = TypeConversion.stringToList(articles.getLabel());
                    ids.forEach(id -> {
                        //权重初始化
                        AtomicInteger oneSort = new AtomicInteger();
                        AtomicInteger twoSort = new AtomicInteger();
                        if (numIsRange(Integer.parseInt(id))) {
                            if (mapLabel.get(id) != null) {
                                mapLabel.put(id, mapLabel.get(id) + oneSort.addAndGet(1));
                            } else {
                                mapLabel.put(id, oneSort.addAndGet(1));
                            }
                        } else {
                            if (mapLabel.get(id) != null) {
                                mapLabel.put(id, mapLabel.get(id) + twoSort.addAndGet(4));
                            } else {
                                mapLabel.put(id, twoSort.addAndGet(4));
                            }
                        }
                    });
                });
                //对map中value进行降序(获取前三个标签)
                List<Map.Entry<String, Integer>> labelMapDecline = mapDecline(mapLabel);
                //获取map中前三个key
                ArrayList<Integer> labelIdList = new ArrayList<>();
                for (Map.Entry<String, Integer> stringIntegerEntry : labelMapDecline) {
                    labelIdList.add(Integer.valueOf(stringIntegerEntry.getKey()));
                }
                List<Long> articleIds = new ArrayList<>();
                HashSet<Integer> set = new HashSet<>();
                //确保推荐3篇文章
                List<Integer> ids = new ArrayList<>();
                //设定一个自增变量，防止死循环
                int auto_i = 0;
                //根据标签id随机推荐文章
                for (Integer labelId : labelIdList) {
                    auto_i++;
                    QueryWrapper<Articles> articlesQueryWrapper = new QueryWrapper<>();
                    articlesQueryWrapper.like("label_translation", twoSortMapper.selectById(labelId).getTagName());
                    List<Articles> articlesList = articlesMapper.selectList(articlesQueryWrapper);
                    //设置重试次数
                    int retryCount = 3;
                    //防止文章重复添加
                    while (true) {
                        retryCount--;
                        Random random = new Random();
                        int i = random.nextInt(articlesList.size());
                        if (set.add(i)) {
                            Articles articles = articlesList.get(i);
                            //防止重复添加
                            if (!articleIds.contains(articles.getId())) {
                                set.add(i);
                                ids.add(i);
                                //拼接文章id
                                articleIds.add(articles.getId());
                                break;
                            }
                        }
                        if (retryCount == 0) {
                            Long count = articlesMapper.selectArticleCount();
                            int i1 = random.nextInt(Math.toIntExact(count));
                            do {
                                if (set.add(i1)) {
                                    Articles articles = articlesMapper.selectArticleIsDelete((long) i1);
                                    //防止重复添加
                                    if (!articleIds.contains(articles.getId())) {
                                        set.add(i1);
                                        ids.add(i1);
                                        //拼接文章id
                                        articleIds.add(articles.getId());
                                    }
                                }
                            } while (ids.size() != auto_i);
                            break;
                        }
                        if (ids.size() == auto_i) {
                            break;
                        }
                    }
                }
                UserRecommend userRecommend = new UserRecommend();
                userRecommend.setUserId(userId);
                userRecommend.setArticleIds(StringUtils.join(articleIds, ","));
                QueryWrapper<UserRecommend> userRecommendQueryWrapper = new QueryWrapper<>();
                userRecommendQueryWrapper.eq("user_id", userId);
                UserRecommend vo = userRecommendMapper.selectOne(userRecommendQueryWrapper);
                if (vo != null) {
                    //更新推荐给用户的文章
                    userRecommendMapper.updateUserRecommend(userId, articleIds.toString());
                } else {
                    userRecommendMapper.insert(userRecommend);
                }
            }
        });
    }

    //判断数字在不在某个范围内
    private boolean numIsRange(int current) {
        return Math.max(1, current) == Math.min(current, 18);
    }

    //对map中value进行降序(获取前三个标签)
    public List<Map.Entry<String, Integer>> mapDecline(Map<String, Integer> map) {
        List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet());
        list.sort((o1, o2) -> o2.getValue() - o1.getValue());
        return list.subList(0, 3);
    }
}
